package com.ggshily.swf;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.ggshily.swf.abc.ABCUtil;
import com.ggshily.swf.tag.ISWFTag;
import com.ggshily.swf.tag.SWFTagFactory;
import com.ggshily.util.Util;
import com.ggshily.util.io.LittleEndianDataInputStream;

public class SWFFile
{
	public static final int COMPRESSED = 0x43;
	public static final int NOT_COMPRESSED = 0x46;
	public static final int FULL = 0x3F;
	
	public int version;
	public int frameRate;
	public int frameCount;
	public Map<Integer, ArrayList<ISWFTag>> tags;
	
	private int offset;
	
	public SWFFile()
	{
		tags = new HashMap<Integer, ArrayList<ISWFTag>>();
	}
	
	public void parse(InputStream is) throws Exception
	{
		LittleEndianDataInputStream dis = new LittleEndianDataInputStream(is);
		
		int compressed = ABCUtil.readU8(dis);
		
		ABCUtil.readU8(dis);
		ABCUtil.readU8(dis);
		
		version = ABCUtil.readU8(dis);
		
//		System.out.println(ABCUtil.readU8(dis));
		
		int length = dis.readInt();
		
		byte[] data = new byte[length];
		
		dis.read(data);
		
		if(compressed == COMPRESSED)
		{
			dis = new LittleEndianDataInputStream(new ByteArrayInputStream(Util.uncompress(data)));
		}
		
//		FileOutputStream fileOutStream = new FileOutputStream("test2.bin");
//		fileOutStream.write(Util.uncompress(data));
//		fileOutStream.flush();
//		fileOutStream.close();
		
		offset = 0;
		
		int size = ABCUtil.readU8(dis) >> 3;
		offset++;
		
		size = (int) (Math.ceil((size * 4) / 8d) + 1);
		dis.skip(size);
		offset += size;
		
		frameRate = dis.readByte();
		frameCount = dis.readShort();
		offset += 3;
		
		browseTables(dis);
	}

	private void browseTables(LittleEndianDataInputStream dis) throws Exception
	{
		int currentTag;
		int step;
		ISWFTag tag;
		
		while(dis.available() > 0)
		{
			int tagHeader = dis.readShort();
			currentTag = ((tagHeader >> 6) & 0x3FF);
			offset += 2;
			
			tag = SWFTagFactory.getSWFTag(currentTag);
			
			tag.setTag(currentTag);
			tag.setOffset(offset);
			step = tagHeader & 0x3F;
			
			if(step >= FULL)
			{
				step = dis.readInt();
				offset += 4;
				tag.setOffset(offset);
			}
			offset += step;
			tag.setEndOffset(offset);
			
			tag.parseData(dis);
			
			addTag(currentTag, tag);
			
		}
		
	}

	private void addTag(int currentTag, ISWFTag tag)
	{
		if(!tags.containsKey(currentTag))
		{
			tags.put(currentTag, new ArrayList<ISWFTag>());
			System.out.println(currentTag);
		}
		tags.get(currentTag).add(tag);
	}
}
